<?php


namespace App\Excel;

use Closure;
use Maatwebsite\Excel\Concerns\FromArray;
use Maatwebsite\Excel\Concerns\WithDrawings;
use Maatwebsite\Excel\Concerns\WithEvents;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Events\AfterSheet;
use Maatwebsite\Excel\Facades\Excel;
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
use PhpOffice\PhpSpreadsheet\Style\Border;
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
use PhpOffice\PhpSpreadsheet\Worksheet\Drawing;

class ExportHandler implements FromArray, WithHeadings, WithEvents, WithDrawings
{
    protected $data;
    protected $headings;
    protected $titles;
    protected $columnWidth = [];//设置列宽       key：列  value:宽
    protected $rowHeight = [];  //设置行高       key：行  value:高
    protected $mergeCells = []; //合并单元格    value:A1:K8
    protected $font = [];       //设置字体       key：A1:K8  value:Arial
    protected $fontSize = [];       //设置字体大小       key：A1:K8  value:11
    protected $bold = [];       //设置粗体       key：A1:K8  value:true
    protected $background = []; //设置背景颜色    key：A1:K8  value:#F0F0F0F
    protected $vertical = [];   //设置定位       key：A1:K8  value:center
    protected $sheetName; //sheet title
    protected $borders = []; //设置边框颜色  key：A1:K8  value:#000000
    protected $images = [];
    /**
     * @var Closure|null
     */
    protected $rowCall;

    public static function get($data, $titles): ExportHandler
    {
        return new self($data, $titles);
    }

    //设置页面属性时如果无效   更改excel格式尝试即可
    //构造函数传值
    public function __construct($data, $titles)
    {
        set_time_limit(0);
        ini_set('memory_limit', '2048M');
        $this->data = $data;
        $this->headings = $this->titles = $titles;
    }

    public function headings(): array
    {
        $_rows = [];
        foreach ($this->headings as $cell) {
            if (is_array($cell)) {
                $_rows[] = $cell['name'];
            } else {
                $_rows[] = $cell;
            }
        }
        return [$_rows];
    }

    /**
     * @return array
     */
    public function array(): array
    {
        $rows = [];
        foreach ($this->data as $item) {
            if ($this->rowCall) {
                $item = $this->getRowCall()($item);
            }
            $rows[] = $item;
        }
        return $rows;
    }

    public function registerEvents(): array
    {
        return [
            AfterSheet::class => function (AfterSheet $event) {
                $i = 0;
                foreach ($this->headings as $k => $cell) {
                    $i++;
                    $rowCode = Coordinate::stringFromColumnIndex($i);
                    if (is_array($cell)) {
                        if (isset($cell['width'])) {
                            $event->sheet->getDelegate()->getColumnDimension($rowCode)->setWidth($cell['width']);
                        } else {
                            $event->sheet->getDelegate()->getColumnDimension($rowCode)->setWidth(14);
                        }
                        if (isset($cell['format'])) {
                            $event->sheet->getDelegate()->getStyle($rowCode)->getNumberFormat()->setFormatCode($cell['format']);
                        } else {
                            $event->sheet->getDelegate()->getStyle($rowCode)->getNumberFormat()->setFormatCode(NumberFormat::FORMAT_TEXT);
                        }
                        if (isset($cell['comment'])) {
                            $event->sheet->getDelegate()->getComment($rowCode . ($k + 1))->getText()
                                ->createTextRun($cell['comment']);
                        }
                    } else {
                        $event->sheet->getDelegate()->getStyle($rowCode)->getNumberFormat()->setFormatCode(NumberFormat::FORMAT_TEXT);
                        $event->sheet->getDelegate()->getColumnDimension($rowCode)->setWidth(14);
                    }
                }
                //设置区域单元格垂直居中
                //$event->sheet->getDelegate()->getStyle('A1:Z1265')->getAlignment()->setVertical('center');
                //设置区域单元格水平居中
                //$event->sheet->getDelegate()->getStyle('A1:Z1265')->getAlignment()->setHorizontal('center');
                //设置列宽

                $rowCode = Coordinate::stringFromColumnIndex(count($this->headings));
                $full = "A1:" . $rowCode . (count($this->data) + 1);
                foreach ($this->columnWidth as $column => $width) {
                    $event->sheet->getDelegate()
                        ->getColumnDimension($column)
                        ->setWidth($width);
                }
                //设置行高，$i为数据行数
                foreach ($this->rowHeight as $row => $height) {
                    $event->sheet->getDelegate()
                        ->getRowDimension($row)
                        ->setRowHeight($height);
                }

                //设置区域单元格垂直居中
                foreach ($this->vertical as $region => $position) {
                    $event->sheet->getDelegate()
                        ->getStyle($region)
                        ->getAlignment()
                        ->setVertical($position);
                }

                //设置区域单元格字体
                if (count($this->font)) {
                    foreach ($this->font as $region => $value) {
                        $event->sheet->getDelegate()
                            ->getStyle($region)
                            ->getFont()->setName($value);
                    }
                } else {
                    $event->sheet->getDelegate()
                        ->getStyle($full)
                        ->getFont()->setName('Arial');
                }

                //设置区域单元格字体大小
                foreach ($this->fontSize as $region => $value) {
                    $event->sheet->getDelegate()
                        ->getStyle($region)
                        ->getFont()
                        ->setSize($value);
                }

                //设置区域单元格字体粗体
                foreach ($this->bold as $region => $bool) {
                    $event->sheet->getDelegate()
                        ->getStyle($region)
                        ->getFont()
                        ->setBold($bool);
                }


                //设置区域单元格背景颜色
                foreach ($this->background as $region => $item) {
                    $event->sheet->getDelegate()->getStyle($region)->applyFromArray([
                        'fill' => [
                            'fillType' => 'linear', //线性填充，类似渐变
                            'startColor' => [
                                'rgb' => $item //初始颜色
                            ],
                            //结束颜色，如果需要单一背景色，请和初始颜色保持一致
                            'endColor' => [
                                'argb' => $item
                            ]
                        ]
                    ]);
                }
                //设置边框颜色
                if (count($this->borders)) {
                    foreach ($this->borders as $region => $item) {
                        $event->sheet->getDelegate()->getStyle($region)->applyFromArray([
                            'borders' => [
                                'allBorders' => [
                                    'borderStyle' => Border::BORDER_THIN,
                                    'color' => ['argb' => $item],
                                ],
                            ],
                        ]);
                    }
                } else {

                    $event->sheet->getDelegate()->getStyle($full)->applyFromArray([
                        'borders' => [
                            'allBorders' => [
                                'borderStyle' => Border::BORDER_THIN,
                                'color' => ['argb' => '000000'],
                            ],
                        ],
                    ]);
                }

                //合并单元格
                $event->sheet->getDelegate()->setMergeCells($this->mergeCells);
                if (!empty($this->sheetName)) {
                    $event->sheet->getDelegate()->setTitle($this->sheetName);
                }
                $event->sheet->getDelegate()->freezePane("B2");
            }
        ];
    }


    public function drawings()
    {
        $result = [];
        if ($this->images) {
            foreach ($this->images as $image) {
                foreach ($image as $k => $v) {
                    $k += 2;
                    ${'drawing' . $k} = new Drawing();
                    //图片路径
                    ${'drawing' . $k}->setPath($v['path']);
                    ${'drawing' . $k}->setWidth($v['width']);
                    ${'drawing' . $k}->setHeight($v['height']);
                    ${'drawing' . $k}->setOffsetY(20);
                    //设置图片列
                    ${'drawing' . $k}->setCoordinates($v['position']);
                    $result[] = ${'drawing' . $k};
                }
            }

        }
        return $result;
    }

    public function download($fileName)
    {
        return Excel::download($this, $fileName);
    }

    #region setter

    /**
     * @param array
     * [
     *    'B' => 40,
     *    'C' => 60
     * ]
     */
    public function setColumnWidth(array $columnwidth)
    {
        $this->columnWidth = array_change_key_case($columnwidth, CASE_UPPER);
        return $this;
    }

    public function setImages(array $images)
    {
        $this->images = $images;
        return $this->images;
    }

    /**
     * @param array
     * [
     *    1 => 40,
     *    2 => 60
     * ]
     */
    public function setRowHeight(array $rowHeight)
    {
        $this->rowHeight = $rowHeight;
        return $this;
    }

    /**
     * @param array
     * [
     *    A1:K7 => '宋体'
     * ]
     */
    public function setFont(array $font)
    {
        $this->font = array_change_key_case($font, CASE_UPPER);
        return $this;
    }

    /**
     * @param array
     * @2020/3/22 10:33
     * [
     *    A1:K7 => true
     * ]
     */
    public function setBold(array $bold)
    {
        $this->bold = array_change_key_case($bold, CASE_UPPER);
        return $this;
    }

    /**
     * @param array
     * @2020/3/22 10:33
     * [
     *    A1:K7 => F0FF0F
     * ]
     */
    public function setBackground(array $background)
    {
        $this->background = array_change_key_case($background, CASE_UPPER);
        return $this;
    }

    /**
     * @param array $mergeCells
     * [
     *    A1:K7
     * ]
     */
    public function setMergeCells(array $mergeCells)
    {
        $this->mergeCells = array_change_key_case($mergeCells, CASE_UPPER);
        return $this;
    }

    /**
     * @param array
     * [
     *    A1:K7 => 14
     * ]
     */
    public function setFontSize(array $fontSize)
    {
        $this->fontSize = array_change_key_case($fontSize, CASE_UPPER);
        return $this;
    }

    /**
     * @param array
     * [
     *    A1:K7 => #000000
     * ]
     */
    public function setBorders(array $borders)
    {
        $this->borders = array_change_key_case($borders, CASE_UPPER);
        return $this;
    }

    /**
     * @return Closure
     */
    public function getRowCall(): Closure
    {
        return $this->rowCall;
    }

    /**
     * @param Closure $rowCall
     * @return ExportHandler
     */
    public function setRowCall(Closure $rowCall): ExportHandler
    {
        $this->rowCall = $rowCall;
        return $this;
    }
    #endregion
}